package com.tencent.sr.iris.activity.service.activity.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.tencent.sr.iris.activity.common.enums.*;
import com.tencent.sr.iris.activity.common.util.ShardingIdUtil;
import com.tencent.sr.iris.activity.interfaces.dto.AwardInfoDTO;
import com.tencent.sr.iris.activity.interfaces.enums.ActivityIdEnum;
import com.tencent.sr.iris.activity.interfaces.enums.IsParticipatedEnum;
import com.tencent.sr.iris.activity.repository.Criteria;
import com.tencent.sr.iris.activity.repository.entity.TIrisActivityAwardRecordDO;
import com.tencent.sr.iris.activity.repository.entity.TIrisUserTaskBatchDataDO;
import com.tencent.sr.iris.activity.repository.entity.TIrisUserTaskRecordDO;
import com.tencent.sr.iris.activity.repository.mapper.TIrisActivityAwardRecordMapper;
import com.tencent.sr.iris.activity.repository.mapper.example.TIrisActivityAwardRecordExample;
import com.tencent.sr.iris.activity.repository.mapper.example.TIrisUserTaskRecordExample;
import com.tencent.sr.iris.activity.repository.singlemapper.TIrisUserTaskBatchDataMapper;
import com.tencent.sr.iris.activity.repository.singlemapper.example.TIrisUserTaskBatchDataExample;
import com.tencent.sr.iris.activity.service.activity.ActivityCommonService;
import com.tencent.sr.iris.activity.service.activity.IrisActivityTaskService;
import com.tencent.sr.iris.activity.service.event.dto.SyncEventDTO;
import com.tencent.sr.iris.activity.service.event.util.ActivityCommonUtilService;
import com.tencent.sr.iris.activity.service.event.vo.TIrisUserTaskBatchDataVO;
import com.tencent.sr.iris.activity.service.util.BeanConvertUtil;
import com.tencent.sr.iris.user.core.service.interfaces.dto.tutor.UserTutorRelationDTO;
import com.tencent.sr.iris.user.core.service.interfaces.dto.user.UserWideDTO;
import com.tencent.sr.iris.user.core.service.interfaces.enums.LeaderTypeEnum;
import com.tencent.sr.iris.user.core.service.interfaces.response.activity.SpecialInviteResponse;
import com.tencent.sr.rmall.material.interfaces.enums.EYesNo;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;

@Slf4j
@Service
public class IrisBatchDataServiceImpl {

    @Resource
    private TIrisUserTaskBatchDataMapper userTaskBatchDataMapper;

    @Resource
    private TIrisActivityAwardRecordMapper activityAwardRecordMapper;

    @Resource
    private IrisActivityTaskService irisActivityTaskService;

    @Resource
    private ActivityCommonService activityCommonService;

    @Resource
    private ActivityCommonUtilService activityCommonUtilService;

    /**
     * 特邀会员的枚举值
     */
    public static final Integer SPECIAL_CODE = Integer.valueOf(LeaderTypeEnum.SPECIAL_LEADER.getCode());

    /**
     * 非特邀会员的枚举值
     */
    public static final Integer UN_SPECIAL_CODE = Integer.valueOf(LeaderTypeEnum.INVALID.getCode());

    public void handleBatchDataSync(SyncEventDTO<TIrisUserTaskRecordDO> dto) {
        TIrisUserTaskRecordDO syncData = dto.getSyncData();
        DbEventType eventType = dto.getEventType();
        if (syncData == null || eventType == null) {
            log.error("同步数据或类型为空，msgKey：{}，事件类型：{}", dto.getMsgKey(),
                    Optional.ofNullable(dto.getEventType())
                            .map(DbEventType::getDescription).orElse("事件类型缺失"));
            return;
        }

        String uid = syncData.getUid();
        String activityId = syncData.getActivityId();
        String taskId = syncData.getTaskId();
        String taskPeriod = syncData.getTaskPeriod();

        TIrisUserTaskBatchDataVO batchDataVO = convertRecordDO2BatchDataDO(syncData);
        handleAdditionalInfo(batchDataVO);
        switch (eventType) {
            case ADD:
                int res = userTaskBatchDataMapper.batchInsertIgnoreSelective(Arrays.asList(batchDataVO));
                log.info("新增{}条跑批记录，uid：{}，activityId:{}，taskId：{}，taskPeriod：{}", res, uid, activityId, taskId, taskPeriod);
                return;
            case UPDATE:
                if (Objects.equals(syncData.getStatus(), EYesNo.YES.getValue())) {
                    int i = deleteBatchData(uid, activityId, taskId, taskPeriod);
                    log.info("软删活动参与记录，同步删除{}条跑批记录，uid：{}，activityId:{}，taskId：{}，taskPeriod：{}", i, uid, activityId, taskId, taskPeriod);
                    return;
                }

                res = userTaskBatchDataMapper.batchInsertIgnoreSelective(Arrays.asList(batchDataVO));
                log.info("更新{}条跑批记录，uid：{}，activityId:{}，taskId：{}，taskPeriod：{}", res, uid, activityId, taskId, taskPeriod);
                return;
            case DELETE:
                res = deleteBatchData(uid, activityId, taskId, taskPeriod);
                log.info("删除{}条跑批记录，uid：{}，activityId:{}，taskId：{}，taskPeriod：{}", res, uid, activityId, taskId, taskPeriod);
                return;
            default:
                log.error("无效事件类型{}，uid：{}，activityId:{}，taskId：{}，taskPeriod：{}", eventType.getDescription(), uid, activityId, taskId, taskPeriod);
        }
    }

    /**
     * 处理额外信息
     *
     * @param batchDataVO
     */
    private void handleAdditionalInfo(TIrisUserTaskBatchDataVO batchDataVO) {
        String uid = batchDataVO.getUid();
        String pid = batchDataVO.getPid();
        Map<String, UserWideDTO> userInfoMap = activityCommonUtilService.queryUserWideMapCache(Arrays.asList(uid, pid));
        UserWideDTO userWideDTO = Optional.ofNullable(userInfoMap.get(uid)).orElseGet(UserWideDTO::new);

        //导师uid
        UserTutorRelationDTO userTutorRelationDTO = activityCommonUtilService.queryUserTutorCache(uid);
        batchDataVO.setAdvisorUid(
                Optional.ofNullable(userTutorRelationDTO.getTutorUid()).orElse(StrUtil.EMPTY));

        //下级特邀信息
        SpecialInviteResponse specialInviteResponse = activityCommonUtilService
                .querySpecialInviteCache(uid);
        boolean uidNotSpecial = !LeaderTypeEnum.SPECIAL_LEADER.getCode()
                .equals(specialInviteResponse.getTag());
        batchDataVO.setUidSpecialInvite(uidNotSpecial ? UN_SPECIAL_CODE : SPECIAL_CODE);
        batchDataVO.setSpecialInviteTime(
                Optional.ofNullable(specialInviteResponse.getTimeStamp()).map(DateUtil::date)
                        .orElse(null));

        //上级特邀信息
        SpecialInviteResponse pidSpecialInviteResponse = activityCommonUtilService
                .querySpecialInviteCache(pid);
        boolean pidNotSpecial = !LeaderTypeEnum.SPECIAL_LEADER.getCode()
                .equals(pidSpecialInviteResponse.getTag());
        batchDataVO.setPidSpecialInvite(pidNotSpecial ? UN_SPECIAL_CODE : SPECIAL_CODE);
        batchDataVO.setSuperiorSpecialInviteTime(
                Optional.ofNullable(pidSpecialInviteResponse.getTimeStamp()).map(DateUtil::date)
                        .orElse(null));

        //下级区域
        Long areaId = getAreaId(uid, userInfoMap);
        batchDataVO.setAreaId(areaId);

        //上级区域
        Long pidAreaId = getAreaId(pid, userInfoMap);
        batchDataVO.setSuperiorAreaId(pidAreaId);

        Long traineeTime = activityCommonService.queryTraineeTime(uid);
        batchDataVO.setTraineeTime(Optional.ofNullable(traineeTime).map(DateUtil::date).orElse(DateUtil.date(0l)));
        batchDataVO.setNickName(userWideDTO.getNickName());
    }

    /**
     * 获取区域id
     *
     * @param uid
     * @param userInfoMap
     * @return
     */
    private Long getAreaId(String uid, Map<String, UserWideDTO> userInfoMap) {
        UserWideDTO userInfo = Optional.ofNullable(userInfoMap.get(uid))
                .orElseGet(UserWideDTO::new);
        List<Long> groupChain = userInfo.getGroupChain();
        if (CollectionUtil.isNotEmpty(groupChain) && groupChain.size() >= 2) {
            //groupChain第二个为大区id
            return Optional.ofNullable(groupChain.get(1)).orElse(0l);
        }
        return 0l;
    }

    /**
     * 查询跑批数据
     *
     * @param uid
     * @param activityId
     * @param taskId
     * @param period
     * @return
     */
    public TIrisUserTaskBatchDataDO queryBatchData(String uid, String activityId,
                                                   String taskId, String period) {
        TIrisUserTaskBatchDataExample example = new TIrisUserTaskBatchDataExample();
        Criteria criteria = example.createCriteria()
                .andPropertyEqualTo(TIrisUserTaskRecordExample.UID, uid)
                .andPropertyEqualTo(TIrisUserTaskRecordExample.ACTIVITY_ID, activityId)
                .andPropertyEqualTo(TIrisUserTaskRecordExample.TASK_ID, taskId);

        if (StrUtil.isNotBlank(period)) {
            criteria.andPropertyEqualTo(TIrisUserTaskRecordExample.TASK_PERIOD, period);
        }

        List<TIrisUserTaskBatchDataDO> batchDataDOList = userTaskBatchDataMapper.selectByExample(example);
        if (CollectionUtils.isNotEmpty(batchDataDOList)) {
            return batchDataDOList.get(0);
        }

        return null;
    }

    /**
     * 删除跑批记录
     *
     * @param uid
     * @param activityId
     * @param taskId
     * @param period
     * @return
     */
    public int deleteBatchData(String uid, String activityId,
                               String taskId, String period) {
        TIrisUserTaskBatchDataExample example = new TIrisUserTaskBatchDataExample();
        Criteria criteria = example.createCriteria()
                .andPropertyEqualTo(TIrisUserTaskRecordExample.UID, uid)
                .andPropertyEqualTo(TIrisUserTaskRecordExample.ACTIVITY_ID, activityId)
                .andPropertyEqualTo(TIrisUserTaskRecordExample.TASK_ID, taskId);

        if (StrUtil.isNotBlank(period)) {
            criteria.andPropertyEqualTo(TIrisUserTaskRecordExample.TASK_PERIOD, period);
        }

        return userTaskBatchDataMapper.deleteByExample(example);
    }

    /**
     * 转换跑批数据
     *
     * @param taskRecordDO
     * @return
     */
    public TIrisUserTaskBatchDataVO convertRecordDO2BatchDataDO(TIrisUserTaskRecordDO taskRecordDO) {
        AwardInfoDTO awardInfoDTO = Optional.ofNullable(
                irisActivityTaskService.getAwardInfoByTaskBizId(taskRecordDO.getTaskId())).orElseGet(AwardInfoDTO::new);
        TIrisUserTaskBatchDataVO batchDataVO = BeanConvertUtil.INSTANCE.convertTaskRecordDO2BatchDataVO(taskRecordDO);
        batchDataVO.setBatchNo("");
        batchDataVO.setOrderFinishTime(taskRecordDO.getOrderFinishTime());
        batchDataVO.setAwardType(awardInfoDTO.getType());
        batchDataVO.setAwardAmount(awardInfoDTO.getValue());
        batchDataVO.setParticipable(TaskBatchDateParticipableEnum.YES.getCode());
        batchDataVO.setUserTaskRecordId(taskRecordDO.getBizId());
        batchDataVO.setAwardInfo(JSONObject.toJSONString(awardInfoDTO));
        batchDataVO.setRemark("");
        batchDataVO.setAwardSendTime(DateUtil.date(0l));
        batchDataVO.setPidSpecialInvite(Integer.valueOf(EYesNo.NO.getValue()));
        batchDataVO.setUidSpecialInvite(Integer.valueOf(EYesNo.NO.getValue()));
        batchDataVO.setSuperiorAreaId(0l);
        batchDataVO.setAreaId(0l);
        batchDataVO.setAdvisorUid(StrUtil.EMPTY);
        batchDataVO.setInviteLimit(taskRecordDO.getInviteLimit());
        batchDataVO.setInviteSeq(taskRecordDO.getInviteSeq());
        if (TaskRecordAwardIssueStatusEnum.ISSUE_SUCCEED.getCode() == taskRecordDO.getAwardIssueStatus()) {
            //进度记录是已发放成功,查询奖品发奖记录,获取奖品发放时间
            TIrisActivityAwardRecordExample example = new TIrisActivityAwardRecordExample();
            example.createCriteria().andPropertyEqualTo(TIrisActivityAwardRecordExample.UID, taskRecordDO.getUid())
                    .andPropertyEqualTo(TIrisActivityAwardRecordExample.ACTIVITY_ID, taskRecordDO.getActivityId())
                    .andPropertyEqualTo(TIrisActivityAwardRecordExample.TASK_ID, taskRecordDO.getTaskId())
                    .andPropertyEqualTo(TIrisActivityAwardRecordExample.TASK_RECORD_ID, taskRecordDO.getBizId())
                    .andPropertyEqualTo(TIrisActivityAwardRecordExample.ISSUE_STATUS, AwardRecordIssueStatusEnum.ISSUE_SUCCEED.getCode())
                    .andPropertyEqualTo(TIrisActivityAwardRecordExample.SHARDING_ID, ShardingIdUtil.sharding(taskRecordDO.getUid()));
            example.setOrderByClause(" id desc ");
            List<TIrisActivityAwardRecordDO> awardRecordDOS = activityAwardRecordMapper
                    .limitSelectByExample(example, 0, 1);
            if (!CollectionUtils.isEmpty(awardRecordDOS)) {
                TIrisActivityAwardRecordDO awardRecordDO = awardRecordDOS.get(0);
                batchDataVO.setAwardSendTime(
                        Optional.ofNullable(awardRecordDO.getCreateTime()).orElseGet(() -> DateUtil.date(0l)));
                //获取外部单号
                JSONObject extInfo = JSON.parseObject(awardRecordDO.getExtInfo());
                String outTradeNo = Optional.ofNullable(extInfo)
                        .map(i -> i.getString("outTradeNo")).orElse(null);
                if (StrUtil.isNotBlank(outTradeNo)) {
                    batchDataVO.setOutTradeNo(outTradeNo);
                }
            }
        }
        //处理进度参数
        if (Objects.equals(batchDataVO.getActivityId(), ActivityIdEnum.MONTH_GIFT.getCode())
                || Objects.equals(batchDataVO.getActivityId(), ActivityIdEnum.SPECIAL_INVITE_REWARD.getCode())) {
            Integer shareCount = Optional.ofNullable(taskRecordDO.getShareCount()).orElse(0);
            Integer commission = Optional.ofNullable(taskRecordDO.getCommission()).orElse(0);
            Integer estimateCommission = Optional.ofNullable(taskRecordDO.getEstimateCommission()).orElse(0);
            String isParticipated = shareCount > 0 || commission > 0 || estimateCommission > 0
                    ? IsParticipatedEnum.YES.name() : IsParticipatedEnum.NO.name();
            batchDataVO.setIsParticipated(isParticipated);
        } else if (Objects.equals(batchDataVO.getActivityId(), ActivityIdEnum.INVITE_GIFT.getCode())) {
            if (!Objects.equals(taskRecordDO.getIsParticipated(), IsParticipatedEnum.LIMITED.name())) {
                String isParticipated = Objects.equals(taskRecordDO.getUserTaskStatus(), UserTaskStatusEnum.FINISHED.getCode())
                        || taskRecordDO.getGmv() > 0 ? IsParticipatedEnum.YES.name() : IsParticipatedEnum.NO.name();
                batchDataVO.setIsParticipated(isParticipated);
            } else {
                batchDataVO.setIsParticipated(IsParticipatedEnum.LIMITED.name());
            }
        } else {
            batchDataVO.setIsParticipated(taskRecordDO.getIsParticipated());
        }

        return batchDataVO;
    }

}
